import json
import os
import socket
import time

from requests import Timeout, JSONDecodeError, ConnectionError

import RequestUtils as ru
import logging
from FirmwareType import FirmwareType

logger = logging.getLogger(__name__)


def return_upgrade_settings(upgrade_type=None):
    """
    升级BIOS固件不保存配置,fpga请求消息体为空
    :param upgrade_type: 升级固件类型
    :return: json字符串
    """
    if upgrade_type is FirmwareType.BIOS:
        return json.dumps({"action": "1"})
    elif upgrade_type is FirmwareType.FPGA:
        return json.dumps({})
    else:
        return json.dumps({"action": "0"})


def return_upgrade_url(host, upgrade_type):
    """
    返回升级请求url
    :param host: 主机地址
    :param upgrade_type: 升级固件类型
    :return: 字符串
    """
    if upgrade_type == FirmwareType.CPLD:
        return f"https://{host}/redfish/v1/UpdateService/Actions/Oem/Chinatelecom/CPLD.FirmwareUpdate"
    elif upgrade_type == FirmwareType.BMC:
        return f"https://{host}/redfish/v1/UpdateService/Actions/Oem/Chinatelecom/BMC.FirmwareUpdate"
    elif upgrade_type == FirmwareType.BIOS:
        return f"https://{host}/redfish/v1/UpdateService/Actions/Oem/Chinatelecom/BIOS.FirmwareUpdate"
    elif upgrade_type == FirmwareType.FPGA:
        return f"https://{host}/redfish/v1/UpdateService/Actions/Oem/Chinatelecom/FPGA.FirmwareUpdate/image1"
    return None


class ZijinUpgradeFirmware():
    def __init__(self, host, username, password):
        """
        :param host: 主机地址
        :param username: 用户名
        :param password: 密码
        """
        self.host = host
        self.username = username
        self.password = password
        self.auth_token = None
        self.session_id = None

    # redfish登录
    def login(self):
        """
        登录
        :return: 登录成功返回True, 登录失败返回False
        """
        url = "https://{}/redfish/v1/SessionService/Sessions".format(self.host)
        account = json.dumps({
            "UserName": self.username,
            "Password": self.password
        }, indent=4, separators=(",", ":")
        )
        headers = {
            "Cache-Control": "no-cache",
            "Content-Type": "application/json"
        }
        try:
            response = ru.send_post(url=url, data=account, headers=headers, file=None)
            if response.status_code == 201:
                self.session_id = response.json()["Id"]
                self.auth_token = response.headers["x-auth-token"]
                return True, "{}-登录成功，token={},session_id={}".format(self.host, self.auth_token, self.session_id)
            elif response.status_code == 400:
                logger.error(response.text)
                return False, "登录失败，用户名或密码错误！"
            else:
                return False, "{}-登录失败！Reason:{}".format(self.host, response.json())
        except Timeout as timeout_error:
            logger.error("Timeout error: %s", timeout_error)
            return False, "登录超时！"
        except JSONDecodeError as e:
            logger.error("JSONDecodeError: %s", e)
            return False, "登录失败，返回值异常！"
        except ConnectionError as e:
            logger.error("NewConnectionError: %s", e)
            return False, "登录失败，网络异常！"
        except OSError as e:
            logger.error("OSError: %s", e)
            return False, "登录失败，网络异常！"
        except Exception as e:
            logger.error("An error occurred: %s", e)
            return False, "登录失败，Reason:{e}"

    # redfish登出
    def logout_redfish(self):
        """
        登出
        :return: 登出成功返回True, 登出失败返回False
        """
        logout_url = "https://{}/redfish/v1/SessionService/Sessions/{}".format(self.host, self.session_id)
        logout_resp = ru.send_delete(url=logout_url, headers=ru.create_general_headers(self.auth_token))
        if logout_resp.status_code == 200:
            return True, "The [{}] is logout!".format(self.host)
        else:
            return False, "The [{}] is logout failed!".format(self.host)

    # 返回升级固件的url
    def return_upload_url(self, upload_type):
        """
        返回上传固件的url
        :param upload_type: 升级固件类型
        :return: 字符串
        """
        if upload_type == FirmwareType.CPLD:
            return f"https://{self.host}/redfish/v1/UpdateService/Actions/Oem/Chinatelecom/CPLD.FirmwareFile"
        elif upload_type == FirmwareType.BMC:
            return f"https://{self.host}/redfish/v1/UpdateService/Actions/Oem/Chinatelecom/BMC.FirmwareFile"
        elif upload_type == FirmwareType.BIOS:
            return f"https://{self.host}/redfish/v1/UpdateService/Actions/Oem/Chinatelecom/BIOS.FirmwareFile"
        elif upload_type == FirmwareType.FPGA:
            return f"https://{self.host}/redfish/v1/UpdateService/Actions/Oem/Chinatelecom/FPGA.FirmwareFile"
        return None

    def check_tcp_connectivity(self, max_retries=30, retry_interval=10, port=443):
        """
        检查TCP连接是否可用
        :param max_retries: 最大重试次数
        :param retry_interval: 间隔时间（秒）
        :param port: 端口号
        :return: True/False
        """
        for _ in range(max_retries):
            try:
                sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
                sock.settimeout(5)
                result = sock.connect_ex((self.host, port))
                if result == 0:
                    logger.info(f"主机{self.host}端口{port}已恢复连通")
                    sock.close()
                    return True, f"主机{self.host}端口{port}已恢复连通"
            except Exception as e:
                logger.error(f"主机 {self.host}端口{port} 连接失败，错误信息：{e}")
            time.sleep(retry_interval)
        logger.error(f"主机{self.host}端口{port}在{max_retries * retry_interval}秒内未恢复连通")
        return False, f"主机{self.host}端口{port}在{max_retries * retry_interval}秒内未恢复连通"

    # 上传固件
    def upload_image(self, upload_type, file_path):
        """
        上传固件
        :param upload_type: 升级固件类型
        :param file_path: 固件文件路径
        :return: True/False
        :return: 字符串
        """
        url = self.return_upload_url(upload_type)
        if url is None:
            return False, "不支持的升级类型"
        # 检查固件文件是否存在
        if not os.path.exists(file_path):
            return False, "固件文件不存在"
        try:
            with open(file_path, 'rb') as f:
                files = {
                    'fwimage': (os.path.basename(file_path), f, 'application/octet-stream')
                }
                headers = {
                    "x-auth-token": self.auth_token,
                    "Accept": "application/json",
                    "User-Agent": "Python/requests",
                    "Connection": "keep-alive"
                }
                logger.info(f"{self.host}-开始上传-{upload_type}固件！")
                response = ru.send_post(url=url, headers=headers, data=None, file=files)

                # 关键修改：安全解析JSON，避免非JSON内容报错
                response_text = response.text  # 获取原始响应内容
                try:
                    response_json = response.json()
                    # 安全访问嵌套字段（避免KeyError）
                    upload_result = response_json.get("Oem", {}).get("Chinatelecom", {}).get("Status", None)
                    if upload_result == 0:
                        return True, "{}-{},固件上传成功！".format(self.host, upload_type)
                    else:
                        return False, "{}-{},固件上传失败！服务器返回：{}".format(self.host, upload_type, response_json)
                except json.JSONDecodeError:
                    response_json = {}  # 避免后续代码因None报错
                    return False, f"警告：服务器返回非JSON内容：{response_text}"
        except Exception as e:
            return False, "{}-{},固件上传失败！Reason:{}".format(self.host, upload_type, e)

    # 获取bios、cpld升级进度
    def check_upgrade_status(self, max_retries=5):
        """
        检查升级状态
        :param max_retries: 最大重试次数
        :return: True/False
        """
        # 实现10分钟超时机制
        timeout = 10 * 60  # 10分钟
        start_time = time.time()
        wait_time = 5 * 60
        logger.info(f"{self.host}-等待{wait_time}秒开始检查[BIOS\\CPLD\\FPGA]升级状态！")
        time.sleep(wait_time)
        retries = 0

        # 定义升级失败状态码 - 修改为列表使其可迭代
        FAILED_STATUS_CODES = [1]  # 假设1表示失败状态，根据实际情况调整

        while retries < max_retries:
            try:
                bios_check_url = f"https://{self.host}/redfish/v1/UpdateService/Actions/Oem/Chinatelecom/BIOS.FirmwareStatus"
                cpld_check_url = f"https://{self.host}/redfish/v1/UpdateService/Actions/Oem/Chinatelecom/CPLD.FirmwareStatus"
                fpga_check_url = f"https://{self.host}/redfish/v1/UpdateService/Actions/Oem/Chinatelecom/FPGA.FirmwareStatus"

                def get_upgrade_process(check_type):
                    url = ''
                    if check_type == FirmwareType.BIOS:
                        url = bios_check_url
                    elif check_type == FirmwareType.CPLD:
                        url = cpld_check_url
                    elif check_type == FirmwareType.FPGA:
                        url = fpga_check_url
                    headers = {
                        "x-auth-token": self.auth_token,
                        "Content-Type": "application/json"}
                    response = ru.send_get(url, headers)
                    return response

                logger.info("{}-请等待[BIOS\CPLD\FPGA]升级完成！".format(self.host))
                # 循环检查升级状态，直到升级完成、失败或超时
                while True:
                    # 检查是否超时
                    if time.time() - start_time > timeout:
                        error_msg = f"{self.host}-升级[BIOS\CPLD\FPGA]固件超时(10分钟)，已停止升级！"
                        logger.error(error_msg)
                        return False, error_msg

                    bios_resp = get_upgrade_process(check_type=FirmwareType.BIOS)
                    cpld_resp = get_upgrade_process(check_type=FirmwareType.CPLD)
                    fpga_resp = get_upgrade_process(check_type=FirmwareType.FPGA)

                    # 检查是否有任何响应返回401状态码（未授权）
                    has_401_status = (bios_resp.status_code == 401 or
                                      cpld_resp.status_code == 401 or
                                      fpga_resp.status_code == 401)

                    if has_401_status:
                        logger.warning(f"{self.host} - 检测到401未授权状态，尝试重新登录...")
                        # 重新执行登录操作
                        login_success, login_msg = self.login()
                        if login_success:
                            logger.info(f"{self.host} - 重新登录成功: {login_msg}")
                            # 重新获取升级状态，跳过当前循环的剩余部分
                            continue
                        else:
                            error_msg = f"{self.host} - 重新登录失败: {login_msg}"
                            logger.error(error_msg)
                            return False, error_msg

                    if bios_resp.status_code == 200 and cpld_resp.status_code == 200 and fpga_resp.status_code == 200:
                        # 安全访问嵌套字段（避免 KeyError）
                        bios_update_status = bios_resp.json().get("Oem", {}).get("Chinatelecom", {}).get("UpdateStatus")
                        cpld_update_status = cpld_resp.json().get("Oem", {}).get("Chinatelecom", {}).get("UpdateStatus")
                        fpga_update_status = fpga_resp.json().get("Oem", {}).get("Chinatelecom", {}).get("UpdateStatus")

                        # 检查是否有任何组件升级失败
                        if bios_update_status in FAILED_STATUS_CODES:
                            error_msg = f"{self.host}-BIOS升级失败，状态码:{bios_update_status}，已停止升级！"
                            logger.error(error_msg)
                            return False, error_msg
                        if cpld_update_status in FAILED_STATUS_CODES:
                            error_msg = f"{self.host}-CPLD升级失败，状态码:{cpld_update_status}，已停止升级！"
                            logger.error(error_msg)
                            return False, error_msg
                        if fpga_update_status in FAILED_STATUS_CODES:
                            error_msg = f"{self.host}-FPGA升级失败，状态码:{fpga_update_status}，已停止升级！"
                            logger.error(error_msg)
                            return False, error_msg

                        # 检查是否全部升级成功
                        if (bios_update_status in (0, 3) and cpld_update_status in (0, 3) and fpga_update_status in (0,
                                                                                                                     3)):
                            logger.info(f"{self.host}-升级[BIOS\CPLD\FPGA]固件成功！")
                            return True, f"{self.host}-升级[BIOS\CPLD\FPGA]固件成功！"
                        else:
                            logger.info(
                                f"{self.host}-BIOS升级状态:{bios_update_status}，CPLD升级状态:{cpld_update_status}，FPGA升级状态: {fpga_update_status}")
                    else:
                        # HTTP请求失败，记录详细错误信息
                        error_msg = f"{self.host} - 获取[BIOS\CPLD\FPGA]升级状态失败，BIOS状态码:{bios_resp.status_code}，CPLD状态码:{cpld_resp.status_code}，FPGA状态码:{fpga_resp.status_code}"
                        logger.error(error_msg)
                        logger.error(
                            f"bios请求url：{bios_check_url}，cpld请求url：{cpld_check_url}，fpga请求url：{fpga_check_url}")

                        # 检查是否是临时性网络问题，如果是则继续尝试，否则直接返回失败
                        if bios_resp.status_code >= 500 or cpld_resp.status_code >= 500 or fpga_resp.status_code >= 500:
                            logger.warning(f"{self.host} - 服务器暂时不可用，将继续尝试...")
                        elif fpga_resp.status_code >= 400 or bios_resp.status_code >= 400 or cpld_resp.status_code >= 400:
                            # 其他4xx错误，继续尝试
                            logger.warning(f"{self.host} - 获取[BIOS\CPLD\FPGA]升级状态失败，将重新尝试获取")
                        else:
                            # 其他错误，直接返回失败
                            return False, error_msg

                    # 每20秒采集一次升级状态
                    time.sleep(20)
            except Exception as e:
                retries += 1
                logger.error(f"{self.host} - 检查[BIOS\CPLD\FPGA]升级状态时出错，第 {retries} 次重试，错误信息: {e}")
                if retries < max_retries:
                    # 重试前等待一段时间
                    time.sleep(5)
                else:
                    error_msg = f"{self.host} - 检查[BIOS\CPLD\FPGA]升级状态失败，已达到最大重试次数 {max_retries}"
                    logger.error(error_msg)
                    return False, error_msg

        error_msg = f"{self.host} - 检查[BIOS\CPLD\FPGA]升级状态失败，请重试！！"
        logger.error(error_msg)
        return False, error_msg

    def check_bmc_upgrade_status(self, max_retries=5):
        """
        检查BMC升级状态
        :param max_retries: 最大重试次数
        :return: True/False
        """
        wait_time = 5 * 60
        logger.info(f"{self.host}-等待{wait_time}秒后开始检查BMC升级状态！")
        time.sleep(wait_time)
        retries = 0
        while retries < max_retries:
            try:
                tcp_connectivity_result, tcp_connectivity_result_msg = self.check_tcp_connectivity()
                if tcp_connectivity_result:
                    login_result, login_msg = self.login()
                    if not login_result:
                        logger.error(f"{self.host}-登录失败，跳过升级！")
                        return False, f"{self.host}-登录失败，跳过升级！"

                    bmc_upgrade_url = f"https://{self.host}/redfish/v1/UpdateService/Actions/Oem/Chinatelecom/BMC.FirmwareStatus"

                    def get_upgrade_process():
                        headers = {
                            "x-auth-token": self.auth_token,
                            "Content-Type": "application/json"}
                        response = ru.send_get(bmc_upgrade_url, headers)
                        return response

                    while True:
                        bmc_resp = get_upgrade_process()

                        if bmc_resp.status_code == 200:
                            bmc_update_status = bmc_resp.json().get("Oem", {}).get("Chinatelecom", {}).get(
                                "UpdateStatus")
                            if bmc_update_status in (0, 3):
                                logger.info(f"BMC升级状态：{bmc_update_status}")
                                return True, f"{self.host}-BMC升级成功！！"
                        else:
                            logger.error(f"{self.host}-获取BMC升级状态失败，状态码:{bmc_resp.status_code}")
                            logger.error(f"bmc请求url：{bmc_upgrade_url}")
                            continue
                    logger.debug(f"{self.host}-BMC URL-{bmc_upgrade_url}-状态码-{bmc_resp.status_code}")
                    return False, f"{self.host}-{tcp_connectivity_result_msg}"
                return False, f"{self.host}-BMC-连通性检查失败，请重试！"
            except Exception as e:
                retries += 1
                logger.error(f"{self.host} - 检查BMC升级状态时出错，第 {retries} 次重试，错误信息: {e}")

                if retries < max_retries:
                    time.sleep(5)
                else:
                    return False, f"{self.host} - 检查BMC升级状态失败，已达到最大重试次数 {max_retries}"
        return False, f"{self.host}-BMC状态检查失败，请重试！"

    # 检查bmc升级状态
    def check_bmc_process(self):
        """
        检查BMC升级状态
        :return: True/False
        """
        url = "https://{}/redfish/v1/UpdateService/Actions/Oem/Chinatelecom/BMC.FirmwareStatus".format(self.host)
        headers = {
            "x-auth-token": self.auth_token,
            "Content-Type": "application/json"}
        response = ru.send_get(url, headers)

        if response.status_code == 200:
            response_json = response.json()
            update_status = response_json.get("Oem", {}).get("Chinatelecom", {}).get("UpdateStatus")
            if update_status == 4:
                logger.info("{}-BMC开始升级，请等待！".format(self.host))
            elif update_status == 0:
                logger.info("{}-BMC升级成功，开始升级CPLD\BIOS固件！！".format(self.host))

    # 强制关机
    def force_power_off(self):
        """
        强制关机
        :return: True/False
        """
        url = "https://{}/redfish/v1/Systems/1/Actions/ComputerSystem.Reset".format(self.host)
        headers = {
            "x-auth-token": self.auth_token,
            "Content-Type": "application/json"}
        data = json.dumps({
            "ResetType": "ForceOff"
        })
        response = ru.send_post(url, headers, data, file=None)
        if response.status_code == 200:
            return True, "{}-强制关机成功！".format(self.host)
        else:
            return False, "{}-强制关机失败！".format(self.host)

    # 开机
    def power_on(self):
        """
        开机
        :return: True/False
        """
        url = "https://{}/redfish/v1/Systems/1/Actions/ComputerSystem.Reset".format(self.host)
        headers = {
            "x-auth-token": self.auth_token,
            "Content-Type": "application/json"}
        data = json.dumps({
            "ResetType": "On"
        })
        response = ru.send_post(url, headers, data, file=None)
        if response.status_code == 200:
            logger.debug("{}-开机成功！".format(self.host))
            return True, "{}-开机成功！".format(self.host)
        else:
            logger.debug("{}-开机失败！".format(self.host))
            return False, "{}-开机失败！".format(self.host)

    # 强制关机再开机
    def force_power_pycle(self):
        """
        强制关机再开机
        :return: True/False
        """
        url = "https://{}/redfish/v1/Systems/1/Actions/ComputerSystem.Reset".format(self.host)
        headers = {
            "x-auth-token": self.auth_token,
            "Content-Type": "application/json"}
        data = json.dumps({
            "ResetType": "ForcePowerCycle"
        })
        response = ru.send_post(url, headers, data, file=None)
        if response.status_code == 200:
            return True, "{}-下发重启操作成功!！".format(self.host)
        return None, f"{self.host}-下发重启操作失败！"

    # 升级任务
    def start_upgrade_task(self, upgrade_type):
        """
        下发升级任务
        :param upgrade_type: 升级类型
        :return: 任务执行状态
        """
        url = return_upgrade_url(self.host, upgrade_type)
        data = return_upgrade_settings(upgrade_type)
        response = ru.send_post(url=url, headers=ru.create_general_headers(self.auth_token, None), data=data, file=None)
        logger.info(f"upgrade_type is {upgrade_type},request's url is {url},data is {data}")
        if response.status_code == 200:
            return True, "{}-{},开始升级任务！".format(self.host, upgrade_type)
        else:
            return False, "{}-{},开始升级任务失败！".format(self.host, upgrade_type)

    # 如果query_firmware_lists中只有bmc,那么直接升级bmc,如果有cpld,升级cpld后强制重启,如果有bios,升级bios后重启卡,如果有cpld/bios,则升级两者重启卡
    # 多个部件升级
    def multiple_upgrade_firmware(self, query_firmware_lists, is_force_restart):
        """
        多部件升级,如果有bmc,则先升级bmc,然后升级cpld/bios,如果没有bmc,则直接升级cpld/bios
        :param is_force_restart: 是否重启，或是否关机生效
        :param query_firmware_lists: 固件升级列表
        :return: 升级是否成功的布尔值和相应消息
        """
        # 检查固件列表长度
        list_length = len(query_firmware_lists)
        if list_length == 0:
            return False, f'{self.host}-固件列表为空!'

        try:
            # 分离 BMC 固件和其他固件
            bmc_firmwares = []
            other_firmwares = []
            for per_firmware in query_firmware_lists:
                if per_firmware['type'] is FirmwareType.BMC:
                    bmc_firmwares.append(per_firmware)
                else:
                    other_firmwares.append(per_firmware)
            # 检查登录状态
            is_login, login_msg = self.login()
            if not is_login:
                logger.error(f"{self.host}-登录失败，跳过升级！")
                return False, f"{self.host}-登录失败，跳过升级！"
            # 处理非 BMC 固件（CPLD/BIOS）
            for per_firmware in other_firmwares:
                upload_result, upload_msg = self.upload_image(upload_type=per_firmware['type'],
                                                              file_path=per_firmware['file_path'])
                logger.info(upload_msg)
                if not upload_result:
                    return False, f"{self.host}-{per_firmware['type']} 固件上传失败！"

                task_result, task_msg = self.start_upgrade_task(upgrade_type=per_firmware['type'])
                logger.info(task_msg)
                if not task_result:
                    return False, f"{self.host}-{per_firmware['type']} 开始升级任务失败！"
            if len(other_firmwares) > 0:
                if is_force_restart:
                    # 检查主机电源状态，如果是关机状态立即开始升级，如果是开机状态，关机进行升级
                    power_status = self.check_card_power_status()
                    if power_status != "Off":
                        power_off_result, power_off_msg = self.force_power_off()
                        if not power_off_result:
                            return power_off_result, power_off_msg
                # 检查 CPLD/BIOS 升级状态
                check_result, check_msg = self.check_upgrade_status()
                if not check_result:
                    logger.error(check_msg)
                    self.logout_redfish()
                    return False, check_msg

            # 处理 BMC 固件
            for per_firmware in bmc_firmwares:
                upload_result, upload_msg = self.upload_image(upload_type=per_firmware['type'],
                                                              file_path=per_firmware['file_path'])
                logger.info(upload_msg)
                if not upload_result:
                    return False, f"{self.host}-{per_firmware['type']} 固件上传失败！"
            if len(bmc_firmwares) > 0:
                start_upgrade_task_result, start_upgrade_task_result_msg = self.start_upgrade_task(
                    upgrade_type=FirmwareType.BMC)
                if not start_upgrade_task_result:
                    return False, f"{self.host}-BMC 开始升级任务失败！"
                # 检查bmc升级状态
                """
                升级BMC主用分区镜像后会重启，重启后BMC会自动升级从用分区镜像，所以不需要等待BMC升级完成后再重启
                """
                check_bmc_upgrade_result, check_bmc_upgrade_result_msg = self.check_bmc_upgrade_status()
                if not check_bmc_upgrade_result:
                    logger.error(check_bmc_upgrade_result_msg)
                    self.logout_redfish()
                    return False, check_bmc_upgrade_result_msg
            other_firmwares_len = len(other_firmwares)
            bmc_firmwares_len = len(bmc_firmwares)
            if other_firmwares_len in (0, 1) and bmc_firmwares_len > 0:
                if not is_force_restart:
                    self.logout_redfish()
                    return True, f"{self.host}-多部件升级成功，请手动重启生效！"
                self.logout_redfish()
                return True, f"{self.host}-多部件升级成功！"
            elif other_firmwares_len > 1:
                if not is_force_restart:
                    self.logout_redfish()
                    return True, f"{self.host}-多部件升级成功，请手动重启生效！"
                self.logout_redfish()
                return True, f"{self.host}-多部件升级成功！"
            else:
                if not is_force_restart:
                    self.logout_redfish()
                    return True, f"{self.host}-单部件升级成功，请手动重启生效！"
                self.logout_redfish()
                return True, f"{self.host}-单部件升级成功！"
        except Exception as e:
            logger.error(f"{self.host}-多部件升级过程中出现异常: {e}")
            return False, f"{self.host}-多部件升级过程中出现异常: {e}"

    def upgrade_bios(self, file_path, is_force_restart):
        """
        升级BIOS单个固件
        :param is_force_restart: 是否重启
        :param file_path: BIOS固件文件路径
        :return: 升级是否成功的布尔值和相应消息
        """
        is_login, login_msg = self.login()
        if not is_login:
            logger.error(login_msg)
            return False, login_msg

        logger.info("开始升级-{}-BIOS固件！".format(self.host))
        # 上传固件
        upload_result, upload_msg = self.upload_image(upload_type=FirmwareType.BIOS, file_path=file_path)
        if not upload_result:
            logger.error(upload_msg)
            return False, upload_msg
        # 开始升级任务
        task_result, task_msg = self.start_upgrade_task(upgrade_type=FirmwareType.BIOS)
        if not task_result:
            logger.error(task_msg)
            return False, task_msg
        # 等待10s
        time.sleep(10)
        logger.info("{}-BIOS-开始升级任务！".format(self.host))
        if not is_force_restart:
            return True, "{}-BIOS-固件上传完成,请手动重启生效!".format(self.host)
        # 强制重启紫金卡
        restart_result, restart_msg = self.force_power_pycle()
        if not restart_result:
            logger.error(restart_msg)
            return False, restart_msg
        # 获取重启结果
        logger.info(restart_msg)
        return True, "{}-BIOS-强制重启-开始升级任务！".format(self.host)

    def upgrade_cpld(self, file_path, is_force_restart):
        """
        升级CPLD单个固件
        :param is_force_restart:
        :param file_path: CPLD固件文件路径
        :return: 升级是否成功的布尔值和相应消息
        """
        is_login, is_login_msg = self.login()
        if not is_login:
            logger.error(is_login_msg)
            return False, is_login_msg

        logger.info("开始升级-{}-CPLD固件！".format(self.host))

        # 上传固件
        upload_task, upload_task_msg = self.upload_image(upload_type=FirmwareType.CPLD, file_path=file_path)
        if not upload_task:
            logger.error(upload_task_msg)
            return False, upload_task_msg
        # 开始升级任务
        task_result, task_result_msg = self.start_upgrade_task(upgrade_type=FirmwareType.CPLD)
        if not task_result:
            logger.error(task_result_msg)
            return False, task_result_msg
        logger.info(task_result_msg)
        time.sleep(10)
        if not is_force_restart:
            return True, "{}-固件上传完成,请手动重启生效!".format(self.host)
        # 强制重启紫金卡
        restart_result, restart_result_msg = self.force_power_pycle()
        if not restart_result:
            logger.error(restart_result_msg)
            return False, restart_result_msg
        # 返回升级结果
        logger.info(restart_result_msg)
        return True, "{}-CPLD-强制重启-开始升级任务！".format(self.host)

    # 单独升级BMC固件
    def upgrade_bmc(self, file_path):
        """
        升级BMC单个固件
        :param file_path: BMC固件文件路径
        :return: True or False
        :param file_path: 文件路径
        :return: True or False
        """
        is_login, is_login_msg = self.login()
        if is_login:
            upload_result, upload_result_msg = self.upload_image(upload_type=FirmwareType.BMC, file_path=file_path)
            if upload_result:
                upgrade_task, upload_result_msg = self.start_upgrade_task(upgrade_type=FirmwareType.BMC)
                if upgrade_task:
                    """
                    等待60秒开始检查bmc连通性，如果检测成功，则开始检查固件升级状态
                    """
                    logger.info(upload_result_msg)
                    time.sleep(60)
                    connectivity_result, connectivity_msg = self.check_tcp_connectivity()
                    if connectivity_result:
                        check_result, check_msg = self.check_upgrade_status()
                        if check_result:
                            logger.info(check_msg)
                            return check_result, check_msg
                        return False, check_msg
                    return connectivity_msg, connectivity_msg
                else:
                    return False, upload_result_msg
            else:
                logger.error(upload_result_msg)
                return False, upload_result_msg
        else:
            logger.error(is_login_msg)
            return False, is_login_msg

    # 升级fpga版本
    def upgrade_fpga(self, file_path, is_force_restart):
        """
        升级FPGA固件
        :param is_force_restart: 是否强制重启
        :param file_path: FPGA固件文件路径
        :return: 升级是否成功的布尔值和相应消息
        """
        is_login, is_login_msg = self.login()
        if not is_login:
            logger.error(is_login_msg)
            return False, is_login_msg
        # 上传固件
        upload_task, upload_task_msg = self.upload_image(upload_type=FirmwareType.FPGA, file_path=file_path)
        if not upload_task:
            logger.error(upload_task_msg)
            return False, upload_task_msg
        # 开始升级任务
        upgrade_task_result, upgrade_task_msg = self.start_upgrade_task(upgrade_type=FirmwareType.FPGA)
        if not upgrade_task_result:
            logger.error(upgrade_task_msg)
            return False, upgrade_task_msg

        if not is_force_restart:
            return True, f"{self.host}-FPGA-固件上传完成,请手动重启生效!"
        # 强制重启紫金卡
        power_off_result, power_off_result_msg = self.force_power_off()
        if not power_off_result:
            logger.error(power_off_result_msg)
            return False, power_off_result_msg
        logout_result, logout_msg = self.logout_redfish()
        if not logout_result:
            logger.error(logout_msg)
            return False, logout_msg
        return True, f"{self.host}-{FirmwareType.FPGA}-固件升级成功！"

    # 重启紫金卡任务
    def restart_card_task(self):
        """
        重启紫金卡任务
        :return: True or False
        """
        self.login()
        self.force_power_pycle()
        self.logout_redfish()

    # 关闭紫金卡任务
    def power_off_task(self):
        """
        关闭紫金卡任务
        :return: True or False
        """
        is_login_result, is_login_msg = self.login()
        if not is_login_result:
            return is_login_result, is_login_msg
        power_off_result, power_off_msg = self.force_power_off()
        if not power_off_result:
            return power_off_result, power_off_msg
        self.logout_redfish()
        return True, f"{self.host}-执行关机操作成功！"

    # 紫金卡开机
    def power_on_task(self):
        """
        紫金卡开机
        :return: True or False
        """
        is_login_result, is_login_msg = self.login()
        if not is_login_result:
            return is_login_result, is_login_msg
        power_on_result, power_on_msg = self.power_on()
        if not power_on_result:
            return power_on_result, power_on_msg
        self.logout_redfish()
        return True, f"{self.host}-执行开机操作成功！"

    def check_card_power_status(self):
        """
        检查紫金卡电源状态
        :return: 电源状态
        """
        logger.debug(f"{self.host}-检查紫金卡电源状态")
        is_login, is_login_msg = self.login()
        if not is_login:
            logger.error(is_login_msg)
            return False, is_login_msg

        check_power_status_url = f'https://{self.host}/redfish/v1/Systems/1'
        headers = {
            "x-auth-token": self.auth_token,
            "Content-Type": "application/json"}
        response = ru.send_get(check_power_status_url, headers=headers)
        if response.status_code == 200:
            power_status = response.json().get('PowerState')
            logger.debug(f"{self.host}-当前电源状态：{power_status}")
            self.logout_redfish()
            return power_status
        else:
            logger.error(f"检查紫金卡电源状态失败，状态码：{response.status_code}，响应内容：{response.text}")
            return None


# 升级单个主机固件
def upgrade_single_host(host_ip, username, password, query_firmware_lists, is_force_restart):
    """
    升级单个主机固件，支持多个部件升级，线程池调用
    :param host_ip: 主机IP地址
    :param username: 用户名
    :param password: 密码
    :param query_firmware_lists: 固件升级列表
    :param is_force_restart: 是否强制重启
    :return: 升级是否成功的布尔值和相应消息
    """
    print(f"vue传递的参数：{query_firmware_lists}，is_force_restart：{is_force_restart}")
    server = ZijinUpgradeFirmware(host_ip, username, password)
    upgrade_task = server.multiple_upgrade_firmware(query_firmware_lists, is_force_restart)
    return upgrade_task


# 重启紫金卡
def restart_card(host_ip, username, password):
    """
    重启紫金卡
    :param host_ip: 主机IP地址
    :param username: 用户名
    :param password: 密码
    :return: 重启是否成功的布尔值和相应消息
    """
    server = ZijinUpgradeFirmware(host_ip, username, password)
    server.restart_card_task()


# 紫金卡关机
def power_off(host_ip, username, password):
    """
    紫金卡关机
    :param host_ip: 主机IP地址
    :param username: 用户名
    :param password: 密码
    :return: 关机是否成功的布尔值和相应消息
    """
    server = ZijinUpgradeFirmware(host_ip, username, password)
    return server.power_off_task()


# 紫金卡关机
def power_on(host_ip, username, password):
    """
    紫金卡开机
    :param host_ip: 主机IP地址
    :param username: 用户名
    :param password: 密码
    :return: 开机是否成功的布尔值和相应消息
    """
    server = ZijinUpgradeFirmware(host_ip, username, password)
    return server.power_on_task()


if __name__ == '__main__':
    pass
